package config

import (
	"context"
)

type F访问列表提供者 func(ctx context.Context) []F访问配置结构

var F访问列表提供者映射 = make(map[string]F访问列表提供者)

func Z注册访问列表提供者(名称 string, 提供者 F访问列表提供者) {
	F访问列表提供者映射[名称] = 提供者
}

type Q请求列表提供者 func(ctx context.Context) []Q请求配置

var Q请求列表提供者映射 = make(map[string]Q请求列表提供者)

func Z注册请求列表提供者(名称 string, 提供者 Q请求列表提供者) {
	Q请求列表提供者映射[名称] = 提供者
}

type S数据库元信息提供者 func(ctx context.Context) []B表结构

var 数据库元信息提供者映射 = make(map[string]S数据库元信息提供者)

func Z注册数据库元信息提供者(名称 string, 提供者 S数据库元信息提供者) {
	数据库元信息提供者映射[名称] = 提供者
}

type P配置结构 struct {
	F访问控制 *F访问控制

	H函数集合 *H函数集合

	Z最大树宽度 int
	Z最大树深度 int

	Z主键生成函数映射 map[string]RowKeyGenerator

	// 数据库字段风格 数据库字段命名风格 请求传递到数据库中
	S数据库字段风格 Z字段风格转换函数

	// JSON字段风格 数据库返回的字段
	JSON字段风格 Z字段风格转换函数

	S数据库元信息 *S数据库元信息

	F访问列表提供者   string
	Q请求列表提供者   string
	S数据库元信息提供者 string

	F访问列表 []F访问配置结构

	Q请求配置集合 *Q请求配置集合
	C查询配置   *C查询配置
	C操作配置   *C操作配置
}

func X新建配置() *P配置结构 {
	配置 := &P配置结构{}
	配置.F访问控制 = X新建访问控制()
	配置.F访问列表提供者 = "db"
	配置.Q请求列表提供者 = "db"
	配置.S数据库元信息提供者 = "db"

	配置.Z最大树宽度 = 5
	配置.Z最大树深度 = 5

	配置.Z主键生成函数映射 = make(map[string]RowKeyGenerator)

	配置.S数据库字段风格 = X蛇形命名
	配置.JSON字段风格 = X驼峰式小写

	配置.H函数集合 = &H函数集合{}
	配置.H函数集合.H函数映射 = make(map[string]*H函数定义)

	return 配置
}

func (配置 *P配置结构) C重新加载() {

	访问配置映射 := make(map[string]F访问配置结构)

	上下文 := context.Background()

	访问列表提供者 := F访问列表提供者映射[配置.F访问列表提供者]

	if 访问列表提供者 != nil {
		配置.F访问列表 = 访问列表提供者(上下文)

		默认最大数量 := 100

		for _, 访问配置 := range 配置.F访问列表 {
			名称 := 访问配置.B别名
			if 名称 == "" {
				名称 = 访问配置.M名称
			}

			if 访问配置.Z字段获取配置 == nil {
				访问配置.Z字段获取配置 = map[string]*FieldsGetValue{}
			}

			if _, 存在 := 访问配置.Z字段获取配置["default"]; !存在 {
				访问配置.Z字段获取配置["default"] = &FieldsGetValue{}
			}

			for 角色, _ := range 访问配置.Z字段获取配置 {
				if 访问配置.Z字段获取配置[角色].MaxCount == nil {
					访问配置.Z字段获取配置[角色].MaxCount = &默认最大数量
				}
			}
			访问配置映射[访问配置.B别名] = 访问配置
		}
	}

	配置.F访问控制.F访问配置映射 = 访问配置映射

	请求列表提供者 := Q请求列表提供者映射[配置.Q请求列表提供者]
	if 请求列表提供者 != nil {
		请求列表 := 请求列表提供者(上下文)
		配置.Q请求配置集合 = X新建请求配置集合(请求列表)
	}

	数据库元信息提供者 := 数据库元信息提供者映射[配置.S数据库元信息提供者]
	if 数据库元信息提供者 != nil {
		配置.S数据库元信息 = X新建数据库元信息(数据库元信息提供者(上下文))
	}

	配置.C查询配置 = &C查询配置{
		F访问控制:   配置.F访问控制,
		H函数集合:   配置.H函数集合,
		Z最大树深度:  配置.Z最大树深度,
		Z最大树宽度:  配置.Z最大树宽度,
		M默认角色函数: 配置.F访问控制.M默认角色函数,
	}

	配置.C操作配置 = &C操作配置{
		Q请求配置:     配置.Q请求配置集合,
		F访问控制:     配置.F访问控制,
		H函数集合:     配置.H函数集合,
		Z主键生成函数映射: 配置.Z主键生成函数映射,
		M默认角色函数:   配置.F访问控制.M默认角色函数,
	}
}

func (配置 *P配置结构) H获取查询配置() *C查询配置 {
	return 配置.C查询配置
}

func (配置 *P配置结构) H获取操作配置() *C操作配置 {
	return 配置.C操作配置
}
